package com.xingchi.tornado.security.model;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.xingchi.tornado.core.constants.HeaderNames;
import com.xingchi.tornado.core.constants.LoginConstants;
import com.xingchi.tornado.core.utils.RequestUtils;
import com.xingchi.tornado.security.enums.LoginSourceEnum;
import com.xingchi.tornado.security.enums.LoginTypeEnum;
import com.xingchi.tornado.utils.BeanUtils;
import lombok.Getter;
import lombok.Setter;
import org.springframework.web.bind.ServletRequestUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 登录数据
 *
 * @author xiaoya
 * @date 2024/9/27 14:28
 */
@Getter
@Setter
public class LoginData<T extends IUser> implements Serializable {

    /**
     * 用户基本信息
     */
    private Long userId;
    private String username;
    private String name;

    /**
     * 登录类型
     */
    private Integer loginType;

    /**
     * 登录来源
     */
    private Integer loginSource;

    /**
     * 用户对应的权限
     */
    @JsonIgnore
    private Set<String> authorities;

    /**
     * 用户数据
     */
    private T user;

    /**
     * 扩展参数
     */
    private Map<String, Object> extra;

    /**
     * 用户客户端信息
     */
    private String ip;
    private String userAgent;

    /**
     * session信息
     */
    private String sessionId;

    /**
     * 是否进行认证
     */
    private boolean authenticated = false;

    private List<String> roleCodeList;
    private List<String> permissionCodeList;

    /**
     * 初始化loginData信息
     *
     * @return  初始化信息
     */
    public static <T extends IUser> LoginData<T> initLoginData() {

        LoginData<T> loginData = new LoginData<>();

        HttpServletRequest request = RequestUtils.getRequest();
        String ip = RequestUtils.getIp();
        loginData.setIp(ip);
        loginData.setUserAgent(request.getHeader(HeaderNames.USER_AGENT));

        HttpSession session = request.getSession();
        loginData.setSessionId(session.getId());

        int loginType = ServletRequestUtils.getIntParameter(request, LoginConstants.LOGIN_TYPE, LoginTypeEnum.USERNAME_PASSWORD.getCode());
        int loginSource = ServletRequestUtils.getIntParameter(request, LoginConstants.LOGIN_SOURCE, LoginSourceEnum.PC.getCode());
        loginData.setLoginType(loginType);
        loginData.setLoginSource(loginSource);

        return loginData;
    }

    public void putExtra(String key, Object value) {
        if (extra == null) {
            extra = new ConcurrentHashMap<>();
        }
        extra.put(key, value);
    }

    public void putExtra(Map<String, Object>  extra) {
        if (this.extra == null) {
            return;
        }
        this.extra.putAll(extra);
    }

    public void setUser(T user) {
        this.user = user;
        BeanUtils.convert(user, this);
        this.setUserId(user.getUserId());
    }

    public Set<String> getAuthorities() {
        // 角色 + 权限
        Set<String> roleAuthority = Optional.ofNullable(roleCodeList).orElse(new ArrayList<>())
                .stream()
                .map(roleCode -> roleCode.startsWith("ROLE_") ? roleCode : "ROLE_" + roleCode)
                .collect(Collectors.toSet());

        Set<String> permissionAuthority = new HashSet<>(Optional.ofNullable(permissionCodeList).orElse(new ArrayList<>()));

        Set<String> result = new HashSet<>();
        result.addAll(roleAuthority);
        result.addAll(permissionAuthority);
        return result;
    }
}
